package cn.exrick.xboot.modules.transport.service.impl;

import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.exception.XbootException;
import cn.exrick.xboot.common.utils.BeanConverterUtil;
import cn.exrick.xboot.common.utils.DateUtils;
import cn.exrick.xboot.common.utils.SecurityUtil;
import cn.exrick.xboot.modules.base.entity.User;
import cn.exrick.xboot.modules.base.enums.DealStateEnum;
import cn.exrick.xboot.modules.base.enums.DealTypeEnum;
import cn.exrick.xboot.modules.base.enums.PaymentTypeEnum;
import cn.exrick.xboot.modules.base.service.WeChatPayService;
import cn.exrick.xboot.modules.transport.entity.DealRecord;
import cn.exrick.xboot.modules.transport.mapper.DealRecordMapper;
import cn.exrick.xboot.modules.transport.param.SaveDealRecordParam;
import cn.exrick.xboot.modules.transport.service.DealRecordService;
import cn.exrick.xboot.modules.transport.vo.DealRecordVo;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 物流公司基本信息接口实现
 * @author gj
 */
@Slf4j
@Service
@Transactional
public class DealRecordServiceImpl extends ServiceImpl<DealRecordMapper, DealRecord> implements DealRecordService {

    @Autowired
    private DealRecordMapper dealRecordMapper;
    @Autowired
    private WeChatPayService weChatPayService;
    @Autowired
    private SecurityUtil securityUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public DealRecordVo saveDealRecord(SaveDealRecordParam param) {
        DealRecord dealRecord = BeanConverterUtil.convertBean(param,DealRecord.class);
        dealRecord.setDealState(DealStateEnum.STAY_PAY.getCode());
        dealRecord.setDealTime(LocalDateTime.now());
        dealRecord.setRelevanceId(param.getRelevanceId());
        dealRecordMapper.insert(dealRecord);
        DealRecordVo dealRecordVo = BeanConverterUtil.convertBean(dealRecord, DealRecordVo.class);
        if (param.getPaymentType().equals(PaymentTypeEnum.WECHAT.getCode())){
            if (Objects.isNull(param.getWxTradeType()) || StrUtil.isEmpty(param.getWxAppTypeCode())){
                throw new XbootException("操作失败,微信支付操作缺少必要参数，请检查WxTradeType，WxAppTypeCode");
            }
            if (param.getDealType().equals(DealTypeEnum.INCOME.getCode())){
                WxPayUnifiedOrderV3Request v3Request = new WxPayUnifiedOrderV3Request();
                v3Request.setDescription(param.getDealDescription());
                v3Request.setOutTradeNo(dealRecord.getId().toString());
                v3Request.setTimeExpire(DateUtils.format(LocalDateTime.now().plusMinutes(CommonConstant.DEAL_TIME_LIMIT), DateUtils.RFC3339));
                WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
                amount.setTotal(dealRecord.getDealAmount());
                amount.setCurrency("CNY");
                v3Request.setAmount(amount);
                if (param.getWxTradeType().equals(TradeTypeEnum.JSAPI)){
                    WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
                    User currUser = securityUtil.getCurrUser();
                    if (StrUtil.isEmpty(currUser.getWxOpenid())){
                        throw new XbootException("当前操作人微信支付信息异常，请重新通过微信授权登录后操作。");
                    }
                    payer.setOpenid(currUser.getWxOpenid());
                    v3Request.setPayer(payer);
                    WxPayUnifiedOrderV3Result.JsapiResult result = weChatPayService.createOrderV3(param.getWxAppTypeCode(),param.getWxTradeType(),v3Request);
                    dealRecordVo.setWechatPayInfo(result);
                    dealRecordVo.setPaymentNumber(result.getPackageValue().substring(10));
                    dealRecord.setPaymentNumber(result.getPackageValue().substring(10));
                }else if (param.getWxTradeType().equals(TradeTypeEnum.NATIVE)){
                    WxPayUnifiedOrderV3Result result = weChatPayService.unifiedOrderV3(param.getWxAppTypeCode(),param.getWxTradeType(),v3Request);
                    dealRecordVo.setCodeUrl(result.getCodeUrl());
                    dealRecord.setPaymentNumber(result.getCodeUrl().substring(10));
                }
            }else {
                //退款
                //收款的流水
                DealRecord relevance = dealRecordMapper.selectById(param.getRelevanceId());
                if(ObjectUtil.isEmpty(relevance)){
                    throw new XbootException("单据中收款流水信息异常，请联系管理员。");
                }
                WxPayRefundV3Request refundV3Request = new WxPayRefundV3Request();
                //旧支付流水
                refundV3Request.setOutTradeNo(relevance.getId().toString());
                //新支付流水
                refundV3Request.setOutRefundNo(dealRecord.getId().toString());
                refundV3Request.setReason("自主申请退款");
                WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
                amount.setRefund(dealRecord.getDealAmount());
                amount.setTotal(relevance.getDealAmount());
                amount.setCurrency("CNY");
                refundV3Request.setAmount(amount);
                WxPayRefundV3Result wxPayRefundV3Result = weChatPayService.refundV3(refundV3Request);
                if ("SUCCESS".equals(wxPayRefundV3Result.getStatus())){
                    dealRecord.setPaymentNumber(wxPayRefundV3Result.getRefundId());
                    log.info("微信退款申请成功，交易流水号id:{},原流水号:{}",dealRecord.getId(),dealRecord.getRelevanceId());
                }else if("PROCESSING".equals(wxPayRefundV3Result.getStatus())){
                    dealRecord.setPaymentNumber(wxPayRefundV3Result.getRefundId());
                    log.info("微信退款退款处理中，交易流水号id:{},原流水号:{}",dealRecord.getId(),dealRecord.getRelevanceId());
                }else if("CLOSED".equals(wxPayRefundV3Result.getStatus())){
                    dealRecord.setPaymentNumber(wxPayRefundV3Result.getRefundId());
                    log.info("微信退款退款关闭，交易流水号id:{},原流水号:{}",dealRecord.getId(),dealRecord.getRelevanceId());
                }else if("ABNORMAL".equals(wxPayRefundV3Result.getStatus())){
                    throw new XbootException("微信退款申请失败,失败状态:"+wxPayRefundV3Result.getStatus());
                }
            }
        }
        dealRecordMapper.updateById(dealRecord);
        return dealRecordVo;
    }

    @Override
    public Boolean cancelDealRecord(Long dealRecordId) {
        weChatPayService.closeOrderV3(dealRecordId);
        return true;
    }
}